package cn.wx.scholar.tool.io;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.lang.StringUtils;
import cn.wx.common.persistence.web.SpringContext;
import cn.wx.common.utils.JSONUtils;
import cn.wx.scholar.core.entity.TxtData;
import cn.wx.scholar.core.service.TxtDataService;

public class BigFileRead {
	
	//设读取文件的缓存为20MB 
	private final static int bufferSize = 20 * 1024 * 1024;
	
	private final static String fPath = "D:\\my_mag\\part";
	private final static String hz = ".txt";
	
	/**
	 * 启动线程数
	 */
	private final static int threadNum = 7;
	
	private ExecutorService threadPool;
	
	public BigFileRead() {
		this.threadPool = Executors.newFixedThreadPool(threadNum);
	}
	
	/**
	 * 将大文件进行分片
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public int splitBigData(final String filePath) throws Exception {
		
        int bufferSize = 20 * 1024 * 1024;//设读取文件的缓存为20MB   
        //建立缓冲文本输入流   
        File file = new File(filePath);//"D:\\mag_papers_0.txt"  
        FileInputStream fileInputStream = new FileInputStream(file);  
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        //注意这里有时会乱码，根据自己的文本存储格式，进行调整
        InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream,"utf-8");  
        BufferedReader input = new BufferedReader(inputStreamReader, bufferSize);
        
        String line;
        int split_ = 0;
        int size = 0;
        BufferedWriter output = null;
        
        try {
        	while((line = input.readLine()) != null) {
            	
            	if(split_ == 0) {
            		output = new BufferedWriter(
                    		new OutputStreamWriter(
                    				new FileOutputStream( 
                    						new File("D:\\my_mag\\part" + (size++) + ".txt")),"utf-8"));
            	}
            	
            	output.append(line + "\r");
            	
            	/**
            	 * 每20000个数据 分一片
            	 */
            	if(split_ > 1998) {
            		output.flush();  
                    output.close();  
                    output = null;
                    split_=0;
            	}else {
            		split_ ++;
            	}
            	
            }
        }catch (Exception e) {
        	
		}finally {
			if(output != null) {
				output.flush();  
	            output.close();  
	            output = null;
			}
		}
       
        input.close();  
        
        
        /**
         * 分片完毕，启动线程
         */
        int subSize = ((size+1)/threadNum) + 1;
        
        for(int i=0;i<=threadNum;i++) {
        	/**
        	 * 开启线程
        	 */
        	
        	int sindex = i*subSize;
        	int eindex = sindex + subSize - 1;
        	
        	if(eindex > size) {
        		eindex = size;
        	}
        	
        	if(sindex <= eindex) {
        		threadPool.execute(new MultiThreadReader(sindex,eindex));
        	}else {
        		break;
        	}
        	
        }
        threadPool.shutdown();
        
        
        return size;
	}
	
	
	public void kcThreadReader(int sindex_,int eindex_) {
        threadPool.execute(new MultiThreadReader(sindex_,eindex_));
		threadPool.shutdown();
	}
	
	
	class MultiThreadReader implements Runnable{
		
		/**
		 * 读取分片文件的开始序号
		 */
		private int startIndex;
		
		private int endIndex;
		
		private List<TxtData> txtDatas;
		
		
		public MultiThreadReader(int startIndex,int endIndex) {
			this.startIndex = startIndex;
			this.endIndex = endIndex;
			txtDatas = new ArrayList<>();
		}
		
		@Override
		public void run() {
			readByTxt();
		}
		
		public void readByTxt(){
			
			/**
			 * 循环读取TXT
			 * 
			 */
			while(startIndex <= endIndex) {
				try {
					String filePath = fPath + (startIndex) + hz;
					BufferedReader input = initBr(filePath);
					
					if(input != null) {
						String line;
						while((line = input.readLine()) != null) {
							process(line, false,startIndex);
						}
					}
		
					input.close();
					input = null;
					/**
					 * 循环结束查看是否还有数据
					 */
					if(txtDatas.size() > 0) {
						process(null, true,startIndex);
					}
					
					File file = new File(filePath);
					file.delete();
					
					startIndex++;
					
				}catch (Exception e) {
					/**
					 * 如果当前文件插入失败 ，发送异常
					 * 继续读取小一个文件
					 */
					txtDatas.clear();
					startIndex++;
					continue;
				}
			}
		}

		/**
		 * 处理数据
		 * @param data
		 * @param isLast
		 */
		private void process(String s,Boolean isLast,int fileName) {

			if(isLast) {
				TxtDataService txtDataService = SpringContext.getBean(TxtDataService.class);
				txtDataService.insertBatch(txtDatas,50);
				txtDatas.clear();
			}
			
			
			if(StringUtils.isNotBlank(s)) {
				TxtData txtData = null;
				txtData = JSONUtils.p(s, TxtData.class);
				txtData.setTxtFile(fileName);
				if(txtData != null) {
					txtDatas.addAll(txtData.newArrayTxtDatas());
					if(txtDatas.size() >= 500) {
						TxtDataService txtDataService = SpringContext.getBean(TxtDataService.class);
						txtDataService.insertBatch(txtDatas,500);
						txtDatas.clear();
					}
				}
			}
				
		}
		
		public int getStartIndex() {
			return startIndex;
		}

		public void setStartIndex(int startIndex) {
			this.startIndex = startIndex;
		}

		public int getEndIndex() {
			return endIndex;
		}

		public void setEndIndex(int endIndex) {
			this.endIndex = endIndex;
		}

		public List<TxtData> getTxtDatas() {
			return txtDatas;
		}

		public void setTxtDatas(List<TxtData> txtDatas) {
			this.txtDatas = txtDatas;
		}

	}
	
	
	
	private BufferedReader initBr(final String filePath) {
		try {
			File file = new File(filePath);
	        FileInputStream fileInputStream = new FileInputStream(file);  
	        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
	        //注意这里有时会乱码，根据自己的文本存储格式，进行调整
	        InputStreamReader inputStreamReader = new InputStreamReader(bufferedInputStream,"utf-8");  
	        BufferedReader input = new BufferedReader(inputStreamReader, bufferSize);
	        return input;
		}catch (Exception e) {
		}
        return null;
	}


}
